package midoo.server.codec;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.json.simple.JSONValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

public class NetStringsDecoder extends ByteToMessageDecoder{
    private static final Logger LOGGER = LoggerFactory.getLogger(NetStringsDecoder.class);

    String lstr;
    enum EState {RLEN, RMSG, TAIL}

    EState state;
    int msglen;

    public NetStringsDecoder() {
        state = EState.RLEN;
        lstr = "";
        msglen = 0;
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
        if (state == EState.RLEN) {
            while (in.readableBytes() > 0) {
                byte x = in.readByte();

                if (x == ':') {
                    msglen = Integer.parseInt(lstr);

                    if (0 != msglen) {
                        state = EState.RMSG;
                    }

                    lstr = "";
                    break;
                } else if (Character.isDigit(x)) {
                    this.lstr += (char)x;
                } else {
                    lstr = "";
                }
            }
        }

        if (state == EState.RMSG) {
            if (in.readableBytes() >= msglen) {
                ByteBuf data = in.readBytes(msglen);
                String jsonStr = new String(data.array());
//                LOGGER.info("NetStringsDecoder from {}:{}", ctx.channel().remoteAddress(), jsonStr);

                Object obj = JSONValue.parse(jsonStr);
                if (obj == null) {
                    LOGGER.warn("NetStringsDecoder parse JSON error: {}", jsonStr);
                } else{
                    out.add(obj);
                }
                state = EState.TAIL;
            }
        }

        if (state == EState.TAIL) {
            if (in.readableBytes() >= 1) {
                Byte tail = in.readByte();
                if (tail != ',') {
                    LOGGER.warn("decode error for no tail");
                }
//                in.discardSomeReadBytes();
                state = EState.RLEN;
            }
        }
    }
}
